library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity alu is
    Port ( inp_A : in  STD_LOGIC_VECTOR (7 downto 0);
           inp_B : in  STD_LOGIC_VECTOR (7 downto 0);
           op_type : in  STD_LOGIC_VECTOR (2 downto 0);
           sh_rot_count : in  STD_LOGIC_VECTOR (2 downto 0);
           is_sh_rot : in  STD_LOGIC;
           cry_in : in  STD_LOGIC;
           alu_out : out  STD_LOGIC_VECTOR (7 downto 0);
           flags_out : out  STD_LOGIC_VECTOR (1 downto 0));
end alu;
 
architecture Behavioral of alu is

alias zero_flag: STD_LOGIC is flags_out(1);
alias cry_flag : STD_LOGIC is flags_out(0);
 
begin

process (inp_A,inp_B,op_type, sh_rot_count, is_sh_rot, cry_in)
variable tmp_op    : STD_LOGIC_VECTOR (8 downto 0);
--variable aux_carry :STD_LOGIC;
variable aux_carry :STD_LOGIC_VECTOR(8 downto 0);

 begin 
-- aux_carry := cry_in;
  if cry_in='1' then
  aux_carry:="000000001";
  else
  aux_carry:="000000000";
  end if;
  
 if is_sh_rot = '1' then
 case op_type is
   when "000" => tmp_op := cry_in & To_stdlogicvector(To_bitvector(inp_A)sll conv_integer(sh_rot_count));
   when "001" => tmp_op := cry_in & To_stdlogicvector(To_bitvector(inp_A)srl conv_integer(sh_rot_count));
    when "010" => tmp_op := cry_in & To_stdlogicvector(To_bitvector(inp_A)sla conv_integer(sh_rot_count));
    when "011" => tmp_op := cry_in & To_stdlogicvector(To_bitvector(inp_A)sra conv_integer(sh_rot_count));
    when "100" => tmp_op := cry_in & To_stdlogicvector(To_bitvector(inp_A)rol conv_integer(sh_rot_count));
    when "101" => tmp_op := cry_in & To_stdlogicvector(To_bitvector(inp_A)ror conv_integer(sh_rot_count));
    when others => tmp_op := (others => '0');
end case;  
 
else
     case op_type is
       when "000" =>  tmp_op := sxt(inp_A, 9) + sxt(inp_B, 9);
       when "001" =>  tmp_op := sxt(inp_A, 9) + sxt(inp_B, 9) + aux_carry;--ext (aux_carry, 9);
       when "010" =>  tmp_op := sxt(inp_A, 9) - sxt(inp_B, 9);
       when "011" =>  tmp_op := sxt(inp_A, 9) - sxt(inp_B, 9) - aux_carry;--ext (aux_carry, 9);
       when "100" =>  tmp_op := cry_in & (inp_A and inp_B);
       when "101" =>  tmp_op := cry_in & (inp_A or inp_B);
       when "110" =>  tmp_op := cry_in & (inp_A xor inp_B);
       when others => tmp_op := (others => '0');
     end case;  
end if;           
   alu_out  <= tmp_op(7 downto 0); 
	cry_flag <= tmp_op(8);
 if tmp_op (7 downto 0) = "0000000" then 
    zero_flag <= '1'; 
 else 
        zero_flag <= '0';
     end if;
  end process;  
end Behavioral;